package com.atguigu.gmall.order.receiver;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.model.enums.PaymentStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.model.payment.PaymentInfo;
import com.atguigu.gmall.order.service.OrderService;
import com.atguigu.gmall.payment.client.PaymentFeignClient;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;

@Component
public class OrderReceiver {

    @Autowired
    private OrderService orderService;

    @Autowired
    private PaymentFeignClient paymentFeignClient;

    @Autowired
    private RabbitService rabbitService;

    /**
     * 取消订单消费者
     * 延迟队列，不能再这里做交换机与队列绑定
     * @param orderId
     * @throws
     */
    @SneakyThrows
    @RabbitListener(queues = MqConst.QUEUE_ORDER_CANCEL)
    public void orderCancel(Long orderId, Message message, Channel channel){
        // 判断订单Id 是否为空！
        // 这里不止要关闭电商平台的交易记录，还需要关闭支付宝的交易记录。
        if (orderId != null){
            OrderInfo orderInfo = orderService.getById(orderId);
            // 涉及到关闭orderInfo ,paymentInfo ,aliPay
            // 如果订单状态是未支付
            if (null != orderInfo && orderInfo.getOrderStatus().equals(ProcessStatus.UNPAID.getOrderStatus().name())){
                //orderService.updateOrderStatus(orderId, ProcessStatus.CLOSED);
                // 关闭过期订单
                // orderService.execExpiredOrder(orderId);
                // 订单创建时就是未付款，判断是否有交易记录产生
                PaymentInfo paymentInfo = paymentFeignClient.getPaymentInfo(orderInfo.getOutTradeNo());
                //如果有支付记录  说明点击了 扫码支付 生成了支付记录
                if (null!=paymentInfo && paymentInfo.getPaymentStatus().equals(PaymentStatus.UNPAID.name())){
                    //查询 支付宝端 是否有交易记录
                    Boolean flag = paymentFeignClient.checkPayment(orderId);
                    if (flag){
                        //true 支付宝端有 记录 说明扫码了 需要关闭支付宝
                        // 有交易记录 ，关闭支付宝 防止用户在过期时间到的哪一个瞬间，付款。
                        Boolean result = paymentFeignClient.closePay(orderId);
                        if (result){
                            //判断用户是否 在时间间隙 支付成功
                            // 如果用户未付款 ，开始关闭订单，关闭交易记录 2:表示要关闭交易记录paymentInfo 中有数据
                            orderService.execExpiredOrder(orderId,"2");

                        }
//                        else{
//                            // 用户已经付款 发送消息给order订单 修改order订单状态
//                            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_PAY,
//                                    MqConst.ROUTING_PAYMENT_PAY,orderId);
//                            //是否需要 改变 payment 状态为PAID？？
//                        }

                    }else {
                        //支付宝端无 交易记录 说明扫码  没有扫码
                        // 在支付宝中没有交易记录，但是在电商中有交易记录
                        //修改 order 和 payment 中的状态 closed
                        orderService.execExpiredOrder(orderId,"2");
                    }

                }else{
                    //没有点击 扫码支付 未生成支付记录 只需要order closed
                    orderService.execExpiredOrder(orderId,"1");
                }

            }
                //   else{订单已支付}  如果orderId为空 不做操作 只消费消息
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

    @RabbitListener(bindings = @QueueBinding(value = @Queue(value = MqConst.QUEUE_PAYMENT_PAY,durable = "true",autoDelete = "false"),
    exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_PAYMENT_PAY),
    key = {MqConst.ROUTING_PAYMENT_PAY}))
    public void updOrder(Long orderId,Message message,Channel channel){
        try {
            if (orderId != null){
                OrderInfo orderInfo = orderService.getOrderInfo(orderId);
                if (null != orderInfo && orderInfo.getOrderStatus().equals(ProcessStatus.UNPAID.getOrderStatus().name())){
                    orderService.updateOrderStatus(orderId,ProcessStatus.PAID);
                    //写一个方法，当订单修改完成后 向库存模块发送消息 减库存
                    orderService.sendOrderStatus(orderId);
                }
            }
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 扣减库存成功，更新订单状态
     * @param msgJson
     * @throws IOException
     */
     @RabbitListener(bindings = @QueueBinding(value = @Queue(value = MqConst.QUEUE_WARE_ORDER,durable = "true",autoDelete = "false"),
     exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_WARE_ORDER),
     key = {MqConst.ROUTING_WARE_ORDER}))
    public void updateOrderStatus(String msgJson,Message message,Channel channel){
         //msgJson 为map转换的字符串 参数有orderId status（‘DEDUCTED’  (已减库存)   ‘OUT_OF_STOCK’  (库存超卖)）
         try {
             if(msgJson != null){
                 Map map = JSON.parseObject(msgJson, Map.class);
                 String orderId = (String) map.get("orderId");
                 String status = (String) map.get("status");
                 OrderInfo orderInfo = orderService.getOrderInfo(Long.parseLong(orderId));
                 if ("DEDUCTED".equals(status)){
                     //减库存 成功 更新订单order 状态
                     orderService.updateOrderStatus(Long.parseLong(orderId),ProcessStatus.WAITING_DELEVER);

                 }else {
                      /*
                        减库存失败！远程调用其他仓库查看是否有库存！
                        true:   orderService.sendOrderStatus(orderId); orderService.updateOrderStatus(orderId, ProcessStatus.NOTIFIED_WARE);
                        false:  1.  补货  | 2.   人工客服。
                     */
                      orderService.updateOrderStatus(Long.parseLong(orderId), ProcessStatus.STOCK_EXCEPTION);
                 }

             }
             channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
         } catch (Exception e) {

             e.printStackTrace();
         }


     }

}